"""

@Time: 2021/2/19 12:13
@Author:
@File: exception_handlers.py
"""
from fastapi import Request, status, FastAPI
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
import redis
import pyfuseki

from models.dto import RESTfulModel
import error_code
from exceptions import TokenVerifyException


def db_connect_exc_handler(request: Request, exc: Exception):
    """
    处理数据库连接错误
    """
    return JSONResponse(
        status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
        content=RESTfulModel(code=error_code.DB_CONNECT_ERROR,
                             data=str(exc)).dict()
    )


def register_exception_handlers(app: FastAPI):
    """
    为 app 注册异常处理器
    """

    @app.exception_handler(TokenVerifyException)
    async def token_verify_exc_handler(request: Request, exc: TokenVerifyException):
        """
        处理 token 认证错误
        """
        return JSONResponse(
            status_code=status.HTTP_403_FORBIDDEN,
            content=RESTfulModel(code=-1,
                                 data=exc.msg).dict()
        )


    @app.exception_handler(RequestValidationError)
    async def request_data_validation_exception_handler(request: Request, exc: RequestValidationError):
        """
        处理API请求中数据验证错误的异常
        将错误信息封装到统一返回格式的 `RESTfulModel` 中
        """
        return JSONResponse(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            content=RESTfulModel(code=-2,
                                 data={'detail': exc.errors(), 'body': exc.body}).dict()
        )


    @app.exception_handler(redis.exceptions.ConnectionError)
    async def redis_connect_exc_handler(request: Request, exc: redis.exceptions.ConnectionError):
        """
        处理 redis 连接错误
        """
        return db_connect_exc_handler(request, exc)


    @app.exception_handler(pyfuseki.exceptions.FusekiConnectError)
    async def fuseki_connect_exc_handler(request: Request, exc: pyfuseki.exceptions.FusekiConnectError):
        """
        处理 fuseki 连接错误
        """
        return db_connect_exc_handler(request, exc)